#include <iostream>
#include <string>
#include <boost/timer.hpp>
#include <boost/thread/thread.hpp>
#include <boost/program_options.hpp>

#include "protonos8.hpp"

static void
setup_location(protonos8::client& m, int loc, uint32_t direction)
{
    uint32_t addr = (loc < 4) ? 0x60000020 + loc*4 : 0x60000060 + (loc-4)*4;

    std::cout << " Setup location " << loc <<
		" [0x" << std::hex << addr <<
		" <- 0x" << direction << std::dec << "].\n";
	m.raw_write(0, addr, direction);
}

static void
m18_write(protonos8::client& m, int loc, uint32_t pattern)
{
    uint32_t addr = (loc < 4) ? 0x60000000 + loc*4 : 0x60000040 + (loc-4)*4;

    m.raw_write(0, addr, pattern);
}

int main(int argc, char *argv[])
{
	try
    {
		namespace po = boost::program_options;
		po::options_description desc("Allowed options");
		desc.add_options()
			("help", "produce help message")
			("host", po::value<std::string>()->default_value("192.168.25.50"), "m211[0] ip address")
			("port", po::value<std::string>()->default_value("1111"), "socket port")
			("delay", po::value<int>()->default_value(0), "spread delay (milliseconds)")
			("pass", po::value<int>()->default_value(1), "total pass counter")
			("exit_state", po::value<int>()->default_value(0), "at exit leave m18 in this state")
		;
		po::variables_map vm;
		po::store(po::parse_command_line(argc, argv, desc), vm);
		po::notify(vm);    

		if (vm.count("help")) {
			std::cout << desc << "\n";
			return 1;
		}
		
		std::cout << "M211@" <<
			vm["host"].as<std::string>() << ":" <<
			vm["port"].as<std::string>() << std::endl;

		protonos8::client m211(vm["host"].as<std::string>().c_str(), vm["port"].as<std::string>().c_str());

		std::size_t delay = vm["delay"].as<int>();

		std::size_t pass = vm["pass"].as<int>();
		std::size_t total = 1;

		for (int ii = 0; ii < 8; ii++) {
			setup_location(m211, ii, 0xff);
		}

		uint32_t pattern = 0x00;

        do {
			
			std::cout << "#" << total++ << "\r" << std::flush;

			for (int ii = 0; ii < 8; ii++) {
				m18_write(m211, ii, pattern);
			}

			pattern = ~pattern & 0xff;

			if (delay)
				boost::this_thread::sleep(boost::posix_time::milliseconds(delay)); 

        } while (!(pass && total > pass));

		std::cout << std::endl;

		for (int ii = 0; ii < 8; ii++) {
			m18_write(m211, ii, vm["exit_state"].as<int>());
		}

	} catch (std::exception& e) {
		std::cerr << "Exception: " << e.what() << "\n";
	}

	return 0;
}
